package com.campus.runrun.serviceImpl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.campus.runrun.common.exception.CustomException;
import com.campus.runrun.common.exception.ResultCodeEnum;
import com.campus.runrun.common.shiro.JWTFilter;
import com.campus.runrun.common.utils.PageResult;
import com.campus.runrun.dao.ErrandDao;
import com.campus.runrun.dao.OrderDao;
import com.campus.runrun.dao.UserDao;
import com.campus.runrun.model.entity.ErrandEntity;
import com.campus.runrun.model.entity.ErrandOrderEntity;
import com.campus.runrun.model.entity.UserEntity;
import com.campus.runrun.model.vo.OrderShowVO;
import com.campus.runrun.service.api.OrderService;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, ErrandOrderEntity> implements OrderService {

    @Autowired
    private ErrandDao errandDao;

    @Autowired
    private UserDao userDao;

    @Override
    public void save(int errandId) {
        // 判断errandId是否存在
        ErrandEntity errandEntity = errandDao.selectById(errandId);
        if (errandEntity == null) {
            throw new CustomException(ResultCodeEnum.ERRAND_ID_NOT_FIND);
        }

        // 判断该errand是否已被接单
        QueryWrapper<ErrandOrderEntity> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("errand_id", errandId);
        List<ErrandOrderEntity> orderEntities = this.baseMapper.selectList(orderQueryWrapper);
        if (orderEntities != null && orderEntities.size() != 0) {
            for (ErrandOrderEntity errandOrderEntity : orderEntities) {
                if (errandOrderEntity.getStatus() != 0) {
                    // 订单状态不是最初始的状态，则说明已经被成功接单
                    throw new CustomException(ResultCodeEnum.ERRAND_HAS_RECEIVED);
                }
            }
        }

        // 接单逻辑
        // 雇佣者id
        int employerId = errandEntity.getEmployerId();
        // 跑腿id
        int employeeId = JWTFilter.getUserInfo().getId();
        ErrandOrderEntity orderInsert = new ErrandOrderEntity();
        orderInsert.setEmployerId(employerId);
        orderInsert.setEmployeeId(employeeId);
        orderInsert.setStatus(0);
        orderInsert.setErrandId(errandId);
        this.baseMapper.insert(orderInsert);

        // 修改errand状态
        ErrandEntity errandUpdate = new ErrandEntity();
        errandUpdate.setId(errandEntity.getId());
        errandUpdate.setStatus(10);
        errandDao.updateById(errandUpdate);
    }

    @Override
    public void confirm(int orderId) {
        // 判断该orderId是否存在
        ErrandOrderEntity errandOrderEntity = this.baseMapper.selectById(orderId);
        if (errandOrderEntity == null) {
            throw new CustomException(ResultCodeEnum.ORDER_ID_NOT_FIND);
        }

        // 判断该订单是否属于 雇佣者
        int employerId = JWTFilter.getUserInfo().getId();
        if (errandOrderEntity.getEmployerId() != employerId) {
            throw new CustomException(ResultCodeEnum.ORDER_EM_NOT_MATCH);
        }

        // 判断该订单状态是否为【初始状态】
        if (errandOrderEntity.getStatus() != 0) {
            throw new CustomException(ResultCodeEnum.ORDER_STATUS_NOT_FIT);
        }

        // 【确认订单逻辑】，该订单状态后移
        ErrandOrderEntity orderUpdate = new ErrandOrderEntity();
        orderUpdate.setId(errandOrderEntity.getId());
        orderUpdate.setStatus(10);
        orderUpdate.setUpdateTime(null);
        this.baseMapper.updateById(orderUpdate);
    }

    @Override
    public PageResult getAll(int page, int size) {
        if (page < 0) {
            page = 1;
        }
        if (size <= 0) {
            size = 4;
        }
        int userId = JWTFilter.getUserInfo().getId();
        QueryWrapper<ErrandOrderEntity> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("employer_id", userId).or().eq("employee_id", userId);
        int totalCount = this.baseMapper.selectCount(orderQueryWrapper);
        PageHelper.startPage(page, size);
        orderQueryWrapper.orderByDesc("create_time");
        List<ErrandOrderEntity> orderEntities = this.baseMapper.selectList(orderQueryWrapper);
        List<OrderShowVO> orderShowVOList = convertOrderEntitiesToOrderShowVOList(orderEntities, userId);
        return new PageResult(orderShowVOList,
                totalCount, size, page);
    }


    @Override
    public PageResult getByFlag(int flag, int page, int size) {
        int userId = JWTFilter.getUserInfo().getId();
        if (page < 0) {
            page = 1;
        }
        if (size <= 0) {
            size = 4;
        }
        QueryWrapper<ErrandOrderEntity> orderQueryWrapper = new QueryWrapper<>();
        if (flag == 0) {
            // 查询【接单】 因此自己是employee
            orderQueryWrapper.eq("employee_id", userId);
        } else {
            // 查询【发布】 因此自己是employer
            orderQueryWrapper.eq("employer_id", userId);
        }
        int totalCount = this.baseMapper.selectCount(orderQueryWrapper);
        PageHelper.startPage(page, size);
        orderQueryWrapper.orderByDesc("create_time");
        List<ErrandOrderEntity> orderEntities = this.baseMapper.selectList(orderQueryWrapper);
        List<OrderShowVO> orderShowVOS = convertOrderEntitiesToOrderShowVOList(orderEntities, userId);
        return new PageResult(orderShowVOS,
                totalCount, size, page);
    }

    @Override
    public void cancelByEr(int orderId) {
        ErrandOrderEntity errandOrderEntity = this.baseMapper.selectById(orderId);
        if (errandOrderEntity == null) {
            throw new CustomException(ResultCodeEnum.ORDER_ID_NOT_FIND);
        }
        int employerId = errandOrderEntity.getEmployerId();
        // 判断雇佣者id和调用者id是否一致
        int userId = JWTFilter.getUserInfo().getId();
        if (employerId != userId) {
            throw new CustomException(ResultCodeEnum.ORDER_EM_NOT_MATCH);
        }
        // 判断订单状态是否为【待接单】
        int status = errandOrderEntity.getStatus();
        if (status != 0) {
            throw new CustomException(ResultCodeEnum.ORDER_STATUS_NOT_FIT);
        }

        // 取消订单逻辑
        ErrandOrderEntity errandOrderUpdate = new ErrandOrderEntity();
        errandOrderUpdate.setId(errandOrderEntity.getId());
        errandOrderUpdate.setStatus(30);
        this.baseMapper.updateById(errandOrderUpdate);
        // errand状态回滚为0
        int errandId = errandOrderEntity.getErrandId();
        ErrandEntity errandUpdate = new ErrandEntity();
        errandUpdate.setId(errandId);
        errandUpdate.setStatus(0);
        errandDao.updateById(errandUpdate);

        // 发布方的取消订单数 + 1
        UserEntity userEntity = userDao.selectById(userId);
        userEntity.setCancelByEmplouerCount(userEntity.getCancelByEmplouerCount() + 1);
        userDao.updateById(userEntity);
    }

    @Override
    public void finish(int orderId) {
        ErrandOrderEntity errandOrderEntity = this.baseMapper.selectById(orderId);
        if (errandOrderEntity == null) {
            throw new CustomException(ResultCodeEnum.ORDER_ID_NOT_FIND);
        }
        int employerId = errandOrderEntity.getEmployerId();
        // 判断调用者是否为雇佣方
        int userId = JWTFilter.getUserInfo().getId();
        if (employerId != userId) {
            throw new CustomException(ResultCodeEnum.ORDER_EM_NOT_MATCH);
        }
        // 判断订单状态是否为【交易中】
        int status = errandOrderEntity.getStatus();
        if (status != 20) {
            throw new CustomException(ResultCodeEnum.ORDER_STATUS_NOT_FIT);
        }
        // 更新订单状态为【交易完成】
        ErrandOrderEntity orderUpdate = new ErrandOrderEntity();
        orderUpdate.setId(errandOrderEntity.getId());
        orderUpdate.setStatus(30);
        this.baseMapper.updateById(orderUpdate);
    }

    @Override
    public List<OrderShowVO> getWeOrder(int employeeId) {
        // 雇佣方Id
        int employerId = JWTFilter.getUserInfo().getId();
        QueryWrapper<ErrandOrderEntity> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("employer_id",employerId);
        orderQueryWrapper.eq("employee_id",employeeId);
        orderQueryWrapper.eq("status",0);
        List<ErrandOrderEntity> errandOrderEntities = this.baseMapper.selectList(orderQueryWrapper);
        if (errandOrderEntities != null && errandOrderEntities.size() != 0) {
            List<OrderShowVO> orderShowVOList = new ArrayList<>();
            for (ErrandOrderEntity errandOrderEntity : errandOrderEntities) {
                OrderShowVO orderShowVO = convertOrderEntityToOrderShowVO(errandOrderEntity, employerId);
                orderShowVOList.add(orderShowVO);
            }
            return orderShowVOList;
        }
        return null;
    }

    @Override
    @Transactional
    public void cancelByEe(int orderId) {
        ErrandOrderEntity errandOrderEntity = this.baseMapper.selectById(orderId);
        if (errandOrderEntity == null) {
            throw new CustomException(ResultCodeEnum.ORDER_ID_NOT_FIND);
        }
        if (errandOrderEntity.getStatus() != 0) {
            throw new CustomException(ResultCodeEnum.ORDER_STATUS_NOT_FIT);
        }
        int employeeId = JWTFilter.getUserInfo().getId();
        if (employeeId != errandOrderEntity.getEmployeeId()) {
            throw new CustomException(ResultCodeEnum.ORDER_EE_NOT_MATCH);
        }
        // 取消订单逻辑
        ErrandOrderEntity errandOrderUpdate = new ErrandOrderEntity();
        errandOrderUpdate.setId(errandOrderEntity.getId());
        errandOrderUpdate.setStatus(30);
        this.baseMapper.updateById(errandOrderUpdate);

        // errand状态回滚为0
        int errandId = errandOrderEntity.getErrandId();
        ErrandEntity errandUpdate = new ErrandEntity();
        errandUpdate.setId(errandId);
        errandUpdate.setStatus(0);
        errandDao.updateById(errandUpdate);

        // 跑退方的取消订单数 + 1
        UserEntity userEntity = userDao.selectById(JWTFilter.getUserInfo().getId());
        userEntity.setCancelByEmploueeCount(userEntity.getCancelByEmploueeCount() + 1);
        userDao.updateById(userEntity);
    }

    private OrderShowVO convertOrderEntityToOrderShowVO(ErrandOrderEntity errandOrderEntity, int userId) {
        if (errandOrderEntity == null)
            return null;
        OrderShowVO orderShowVO = new OrderShowVO();
        int employerId = errandOrderEntity.getEmployerId();
        int employeeId = errandOrderEntity.getEmployeeId();
        // 订单对方Id
        int toId;
        boolean isEmployer;
        if (employerId == userId) {
            toId = employeeId;
            isEmployer = true;
        } else {
            toId = employerId;
            isEmployer = false;
        }
        // 封装订单对方用户信息
        UserEntity userEntity = userDao.selectById(toId);
        orderShowVO.setHeadPortrait(userEntity.getHeadPortrait());
        orderShowVO.setUsername(userEntity.getUsername());
        // 封装跑腿需求信息
        int errandId = errandOrderEntity.getErrandId();
        ErrandEntity errandEntity = errandDao.selectById(errandId);
        BeanUtils.copyProperties(errandEntity, orderShowVO);
        // 封装订单信息
        orderShowVO.setId(errandOrderEntity.getId());
        orderShowVO.setStatus(errandOrderEntity.getStatus());
        orderShowVO.setCreateTime(errandOrderEntity.getCreateTime());
        // 订单对方id
        orderShowVO.setOppositeId(toId);
        orderShowVO.setIsEmployer(isEmployer);
        return orderShowVO;
    }

    private List<OrderShowVO> convertOrderEntitiesToOrderShowVOList(List<ErrandOrderEntity> orderEntities, int userId) {
        if (orderEntities != null && orderEntities.size() != 0) {
            List<OrderShowVO> orderShowVOList = new ArrayList<>();
            for (ErrandOrderEntity errandOrderEntity : orderEntities) {
                OrderShowVO orderShowVO = convertOrderEntityToOrderShowVO(errandOrderEntity, userId);
                orderShowVOList.add(orderShowVO);
            }
            return orderShowVOList;
        }
        return null;
    }
}